package zeroj.web.dispatch;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import zeroj.helper.ClassLoaderUtil;
import zeroj.web.action.IAction;

/**
 * 
 * 
 * @author lyl(lylsir at gmail dot com)
 * 
 * @since 1.0
 * 
 * 2008-9-9
 */
public final class ActionMapper {

	private Map<String, ActionInfo> actionInfos = new HashMap<String, ActionInfo>();
	private Map<Class<?>, ActionInfo> actions = new HashMap<Class<?>, ActionInfo>();
	private String packageNames;
	
	public ActionMapper(String packageNames) {
		
		this.packageNames = packageNames;
	}
	public void init() {
		
		String[] packages = packageNames.split(",");
		for(String packageName : packages) {
			
			parseClasses(packageName);
		}
	}
	
	private void parseClasses(String packageName) {
		
		List<Class<?>> classes = ClassLoaderUtil.loadPackageClasses(packageName.trim(), true);
		for(Class<?> clz : classes) {
			
			if(! clz.isInterface() && IAction.class.isAssignableFrom(clz) && 
					! Modifier.isAbstract(clz.getModifiers()) && Modifier.isPublic(clz.getModifiers())) {
				
				ActionInfo info = ActionInfoParser.parse(packageName, clz);
				actionInfos.put(info.getPath(), info);
				actions.put(clz, info);
			}
		}
	}
	public ActionMapping getActionMapping(String path) {
		
		ActionInfo info = null;
		List<String> params = new ArrayList<String>();
		do {
			info = actionInfos.get(path);
			if(info != null)
				break;
			int slash = path.lastIndexOf('/');
			if(slash + 1 < path.length()) {
				String param = path.substring(slash + 1);
				params.add(param);
			}
			if(slash <= 0)
				break;
			path = path.substring(0, slash);
		} while(path.length() > 0);
		if(info != null) {
			ActionMapping mapping = new ActionMapping();
			mapping.setInfo(info);
			return mapping;
		}
		return null;
	}
	
	public ActionInfo getActionInfo(Class<?> clz) {
		
		return actions.get(clz);
	}
}
